package main.java.FSMDE.controllers;

import java.util.ArrayList;

import main.java.FSMDE.controllers.listeners.ITransitionEventListener;
import main.java.FSMDE.infrastructure.IProjectContext;
import main.java.FSMDE.models.Component;
import main.java.FSMDE.models.Interface;
import main.java.FSMDE.models.Operations;
import main.java.FSMDE.models.Transition;
import main.java.FSMDE.models.TransitionControl;
import main.java.FSMDE.models.TransitionFunctional;
import main.java.FSMDE.models.TransitionType;
import main.java.FSMDE.views.ITransitionView;


public class TransitionController extends BaseController implements
		ITransitionController {

	private Transition pendingTransition;
	private ITransitionView transitionView;
	private ArrayList<ITransitionEventListener> listeners;
	private Iterable<Transition> transitionCollection;
	private Operations operation;

	public TransitionController(IProjectContext projectContext,
			ITransitionView transitionView) {
		super(projectContext);
		pendingTransition = Transition.create("", TransitionType.Control);
		this.listeners = new ArrayList<ITransitionEventListener>();
		this.transitionCollection = projectContext.getAllTransitions();
		this.setTransitionView(transitionView);
		this.operation = Operations.None;
	}

	@Override
	public void create() {
		this.pendingTransition = null;
		this.operation = Operations.Creating;
		this.transitionView.setOperation(this.operation);
		this.transitionView.setInterfaces(this.getContextInterfaces());
		this.transitionView.showView();
		this.operation = Operations.Creating;
	}

	private Iterable<Interface> getContextInterfaces() {
		ArrayList<Interface> interfaces = new ArrayList<Interface>();

		for (ITransitionEventListener listener : listeners) {
			if (listener instanceof DiagramController) {
				for (Interface interface0 : ((DiagramController) listener)
						.getDiagram().getInterfaces()) {
					interfaces.add(interface0);
				}
			}
		}
		return interfaces;
	}

	@Override
	public void create(Transition transition) {
		this.operation = Operations.Updating;
		this.pendingTransition = transition;
		this.transitionView.setOperation(this.operation);
		this.transitionView.setTransitionName(transition.getName());
		this.transitionView.setTransitionType(transition.getType());
		this.transitionView.setInterfaces(this.getContextInterfaces());
		// this.transitionView.setInterfaces(
		// this.projectContext.getAllInterfaces() );
		this.transitionView
				.setTransitionSourceInterface(transition.getSource());
		this.transitionView.setTransitionDestinationInterface(transition
				.getDestination());
		this.transitionView.setTransitionTypeEnable(false);
		switch (transition.getType()) {
		case Functional:
			this.transitionView
					.setFunctionName(((TransitionFunctional) transition)
							.getFunctionName());
			break;
		case Control:
			Component compTrigger = ((TransitionControl) transition)
					.getTriggerComponent();
			if (compTrigger != null)
				this.transitionView.setComponentTrigger(compTrigger);
			break;
		}
		this.transitionView.showView();
	}

	@Override
	public ITransitionView getTransitionView() {
		return this.transitionView;
	}

	@Override
	public void addSubscriber(ITransitionEventListener listener) {
		this.listeners.add(listener);
	}

	@Override
	public boolean addTransition() {
		String name = this.transitionView.getTransitionName();
		if ((this.operation == Operations.Creating)
				&& (!this.validTransitionName(name))) {
			return false;
		}
		if (this.operation == Operations.Updating) {
			this.pendingTransition.setName(name);
			if (this.pendingTransition.getDestination() != null) {
				this.pendingTransition.getDestination().getTransitions()
						.remove(this.pendingTransition);
			}
			this.pendingTransition.setDestination(null);
			if (this.pendingTransition.getSource() != null) {
				this.pendingTransition.getSource().getTransitions()
						.remove(this.pendingTransition);
			}
			this.pendingTransition.setSource(null);
		} else {
			this.pendingTransition = Transition.create(name,
					this.transitionView.getTransitionType());
		}

		if (this.transitionView.getSourceInterface() != null) {
			this.pendingTransition.setSource(this.transitionView
					.getSourceInterface());
			this.transitionView.getSourceInterface().getTransitions()
					.add(this.pendingTransition);
		}
		if (this.transitionView.getDestinationInterface() != null) {
			this.pendingTransition.setDestination(this.transitionView
					.getDestinationInterface());
			this.transitionView.getDestinationInterface().getTransitions()
					.add(this.pendingTransition);
		}
		switch (this.pendingTransition.getType()) {
		case Functional:
			((TransitionFunctional) this.pendingTransition)
					.setFunctionName(this.transitionView.getFunctionName());
			break;
		case Control:
			((TransitionControl) this.pendingTransition)
					.setTriggerComponent(this.transitionView
							.getComponentTrigger());
			break;
		}

		for (ITransitionEventListener listener : listeners) {
			try {
				listener.handleCreatedEvent(this.pendingTransition);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	@Override
	public void setTransitionView(ITransitionView transitionView) {
		this.transitionView = transitionView;
		this.transitionView.setController(this);
	}

	@Override
	public boolean validTransitionName(String transitionName) {
		if (transitionName.equals("")) {
			return false;
		}
		for (Transition transition : transitionCollection) {
			if (transition.getName().equals(transitionName)) {
				return false;
			}
		}
		return true;
	}

	@Override
	public void cancelPendingTransitionAction() {
		this.pendingTransition = null;

	}
}
